跳到主要内容

await 也需要 catch

· 阅读需 4 分钟

总把外行当内行,遇见问题总抓狂

不记得在哪里看了这么一句话:“在 js 中尽量不写 try...catch ,因为会拖累进程,甚至拖垮程序。每一个 try..catch 都将创建一个独立的内存,需要先执行一遍,然后看一下有没有错误,没有错误再返回源执行栈事件进行执行。“

当时,看见这句话,若获珍宝。巴不得在自己的项目中可以一个 try...catch 没有,也不能造成性能不足。

直到,昨晚一个小时一点点的打印找关于 triggerUncaughtException 的错,才发现,这真是“外行看热闹,内行看门道。半瓶子看自以为是和瞎几把信外行的瞎几把说”。

性能关键结论​

场景性能影响数据参考 (V8 引擎)
​​无异常的 try/catch几乎无损耗( <1% 差异)每秒执行 1 亿次无感知
​​高频抛出异常​​显著下降(10~100 倍)每秒处理异常 ≤1 万次
​​嵌套 try/catch作用域管理有轻微损耗单层 vs 五层损耗差约 5%

正确性 >> 性能​​:牺牲 1% 性能换取健壮的错误处理是值得的。只有对性能极其敏感的核心模块(如游戏引擎、高频交易系统),才需要抠 try/catch 的细节。

引擎优化原理​

  1. 无异常路径的「快速通道」​​ V8 会对未触发异常的 try 代码块做内联缓存优化(Inline Caching),跳过异常监控逻辑。 类似 if/else 的​​预测执行机制​​,不影响主线程性能。
  2. ​​仅当 throw 时触发「慢速路径」​​ 异常对象需要生成堆栈跟踪(Stack Trace),消耗 CPU。 垃圾回收压力增大(频繁创建/销毁 Error 对象)。

极端场景性能陷阱​

  1. 高频异常抛出(灾难级性能)​
// ❌ 错误用法:将异常用于正常控制流
function validate(num) {
try {
if (num < 0) throw new Error('Negative');
return num;
} catch (e) {
return 0;
}
}

// ✅ 优化方案:用条件判断代替异常
function validate(num) {
return num < 0 ? 0 : num;
}

性能对比​​:改用条件判断后,速度提升 ​​50~100 倍​​。2. ​​热代码路径中的冗余 try/catch

// ❌ 不必要的 try/catch 包裹循环
try {
for (let i = 0; i < 1e6; i++) {
// 高频执行代码
}
} catch (e) {}

// ✅ 将 try/catch 移出循环
for (let i = 0; i < 1e6; i++) {
try {
/* 单次操作 */
} catch (e) {}
}

性能对比​​:外层包裹导致引擎无法优化,速度下降 ​​5~10%​​。

建议

  1. 必要错误处理​​:对数据库、网络请求、文件 IO 等​​异步操作必须用 try/catch。
  2. 避免异常滥用​​:​​不要用 throw 替代条件判断​​(如参数校验)。
  3. 全局兜底​​:用 process.on('unhandledRejection') 或 window.onerror 捕获漏网之鱼。
  4. 性能敏感场景​​:对高频执行的数学计算、排序算法等,优先用 if 防御而非 try。